<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
</body>
<script>
  class MyPromise {
    // 构造方法
    constructor(executor) {
      // 初始化值
      this.initValue()
      // 初始化this指向
      this.initBind()
      // 执行传进来的函数
      try {
        // 执行传进来的函数
        executor(this.resolve, this.reject)
      } catch (error) {
        // 捕捉到错误直接执行reject
        this.reject(error)
      }
    }

    initBind() {
      // 初始化this
      this.resolve = this.resolve.bind(this)
      this.reject = this.reject.bind(this)
    }

    initValue() {
      // 初始化值
      this.PromiseResult = null // 终值
      this.PromiseState = 'pending' // 状态
      this.onFulfilledCallbacks = [] // 保存成功回调
      this.onRejectedCallbacks = [] // 保存失败回调
    }

    resolve(value) {
      // state是不可变的
      if (this.PromiseState !== 'pending') return
      // 如果执行resolve，状态变为fulfilled
      this.PromiseState = 'fulfilled'
      // 终值为传进来的值
      this.PromiseResult = value

      // 执行保存的成功回调
      while (this.onFulfilledCallbacks.length) {
        this.onFulfilledCallbacks.shift()(this.PromiseResult)
      }
    }

    reject(reason) {
      // state是不可变的
      if (this.PromiseState !== 'pending') return
      // 如果执行reject，状态变为rejected
      this.PromiseState = 'rejected'
      // 终值为传进来的reason
      this.PromiseResult = reason
      // 执行保存的失败回调
      while (this.onRejectedCallbacks.length) {
        this.onRejectedCallbacks.shift()(this.PromiseResult)
      }
    }

    then(onFulfilled, onRejected) {
      // 接收两个回调 onFulfilled, onRejected

      // 参数校验，确保一定是函数
      onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
      onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }


      var thenPromise = new MyPromise((resolve, reject) => {

        const resolvePromise = cb => {
          setTimeout(() => {
            try {
              const x = cb(this.PromiseResult)
              if (x === thenPromise) {
                // 不能返回自身哦
                throw new Error('不能返回自身。。。')
              }
              if (x instanceof MyPromise) {
                // 如果返回值是Promise
                // 如果返回值是promise对象，返回值为成功，新promise就是成功
                // 如果返回值是promise对象，返回值为失败，新promise就是失败
                // 谁知道返回的promise是失败成功？只有then知道
                x.then(resolve, reject)
              } else {
                // 非Promise就直接成功
                resolve(x)
              }
            } catch (err) {
              // 处理报错
              reject(err)
              throw new Error(err)
            }
          })
        }

        if (this.PromiseState === 'fulfilled') {
          // 如果当前为成功状态，执行第一个回调
          resolvePromise(onFulfilled)
        } else if (this.PromiseState === 'rejected') {
          // 如果当前为失败状态，执行第二个回调
          resolvePromise(onRejected)
        } else if (this.PromiseState === 'pending') {
          // 如果状态为待定状态，暂时保存两个回调
          // 如果状态为待定状态，暂时保存两个回调
          this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled))
          this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected))
        }
      })

      // 返回这个包装的Promise
      return thenPromise
    }

//  接收一个Promise数组，数组中如有非Promise项，则此项当做成功
//  如果所有Promise都成功，则返回成功结果数组
//  如果有一个Promise失败，则返回这个失败结果
    static all(promises) {
      const result = []
      let count = 0
      return new MyPromise((resolve, reject) => {
        const addData = (index, value) => {
          result[index] = value
          count++
          if (count === promises.length) resolve(result)
        }
        promises.forEach((promise, index) => {
          if (promise instanceof MyPromise) {
            promise.then(res => {
              addData(index, res)
            }, err => reject(err))
          } else {
            addData(index, promise)
          }
        })
      })
    }

// 接收一个Promise数组，数组中如有非Promise项，则此项当做成功
// 哪个Promise最快得到结果，就返回那个结果，无论成功失败
    static race(promises) {
      return new MyPromise((resolve, reject) => {
        promises.forEach(promise => {
          if (promise instanceof MyPromise) {
            promise.then(res => {
              resolve(res)
            }, err => {
              reject(err)
            })
          } else {
            resolve(promise)
          }
        })
      })
    }

// 接收一个Promise数组，数组中如有非Promise项，则此项当做成功
// 把每一个Promise的结果，集合成数组，返回
    static allSettled(promises) {
      return new Promise((resolve, reject) => {
        const res = []
        let count = 0
        const addData = (status, value, i) => {
          res[i] = {
            status,
            value
          }
          count++
          if (count === promises.length) {
            resolve(res)
          }
        }
        promises.forEach((promise, i) => {
          if (promise instanceof MyPromise) {
            promise.then(res => {
              addData('fulfilled', res, i)
            }, err => {
              addData('rejected', err, i)
            })
          } else {
            addData('fulfilled', promise, i)
          }
        })
      })
    }

// 接收一个Promise数组，数组中如有非Promise项，则此项当做成功
// 如果有一个Promise成功，则返回这个成功结果
// 如果所有Promise都失败，则报错
    static any(promises) {
      return new Promise((resolve, reject) => {
        let count = 0
        promises.forEach((promise) => {
          promise.then(val => {
              resolve(val)
          }, err => {
            count++
            if (count === promises.length) {
                reject(new AggregateError('All promises were rejected'))
            }
          })
        })
      })
    }
  }
</script>
</html>